home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / od-beos / beos.cpp next >
C/C++ Source or Header  |  1998-01-20  |  20KB  |  977 lines

  1. /* 
  2.  * UAE - The Un*x Amiga Emulator
  3.  *
  4.  * BeBox port specific stuff
  5.  *
  6.  * (c) 1996-1997 Christian Bauer
  7.  * (c) 1996 Patrick Hanevold
  8.  */
  9.  
  10. #include <AppKit.h>
  11. #include <InterfaceKit.h>
  12. #include <KernelKit.h>
  13. #include <MediaKit.h>
  14. #include <StorageKit.h>
  15. #include <device/Joystick.h>
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <signal.h>
  21. #include <getopt.h>
  22.  
  23. #include "osdep/beos.h"
  24.  
  25.  
  26. /*
  27.  *  The window in which the Amiga graphics are displayed, handles I/O
  28.  */
  29.  
  30. class BitmapView;
  31.  
  32. class UAEWindow : public BWindow {
  33. public:
  34.     UAEWindow(BRect frame, BBitmap *bitmap);
  35.     virtual bool QuitRequested(void);
  36.     virtual void MessageReceived(BMessage *msg);
  37.  
  38. private:
  39.     void request_floppy(char *title, int drive_num);
  40.  
  41.     BitmapView *main_view;
  42. };
  43.  
  44.  
  45. /*
  46.  *  A simple view class for blitting a bitmap on the screen
  47.  */
  48.  
  49. class BitmapView : public BView {
  50. public:
  51.     BitmapView(BRect frame, BBitmap *bitmap);
  52.     virtual void Draw(BRect update);
  53.     virtual void MouseMoved(BPoint point, ulong transit, BMessage *message);
  54.     void Draw(BRect from, BRect to);
  55.  
  56. private:
  57.     BBitmap *the_bitmap;
  58. };
  59.  
  60.  
  61. /*
  62.  *    LED
  63.  */
  64.  
  65. class LEDView : public BView {
  66. public:
  67.     LEDView(BRect frame, rgb_color active, rgb_color idle);
  68.     virtual void Draw(BRect update);
  69.     void SetState(bool new_state);
  70.  
  71. private:
  72.     BRect bounds;
  73.     rgb_color active_color;
  74.     rgb_color idle_color;
  75.     bool state;
  76. };
  77.  
  78.  
  79. // Messages
  80. const ulong MSG_INSERT_DF0 = 'idf0';
  81. const ulong MSG_EJECT_DF0 = 'edf0';
  82. const ulong MSG_INSERT_DF1 = 'idf1';
  83. const ulong MSG_EJECT_DF1 = 'edf1';
  84. const ulong MSG_INSERT_DF2 = 'idf2';
  85. const ulong MSG_EJECT_DF2 = 'edf2';
  86. const ulong MSG_INSERT_DF3 = 'idf3';
  87. const ulong MSG_EJECT_DF3 = 'edf3';
  88. const ulong MSG_FR1 = 'mfr1';
  89. const ulong MSG_FR2 = 'mfr2';
  90. const ulong MSG_FR3 = 'mfr3';
  91. const ulong MSG_FR4 = 'mfr4';
  92. const ulong MSG_FR5 = 'mfr5';
  93. const ulong MSG_FR6 = 'mfr6';
  94. const ulong MSG_FR7 = 'mfr7';
  95. const ulong MSG_RESET = 'rset';
  96. const ulong MSG_DEBUG = 'dbug';
  97. const ulong MSG_REDRAW = 'draw';
  98.  
  99.  
  100. // LED colors
  101. const rgb_color PowerDark = {0x40, 0x00, 0x00, 0};
  102. const rgb_color PowerLight = {0xff, 0x00, 0x00, 0};
  103. const rgb_color DriveDark = {0x00, 0x40, 0x00, 0};
  104. const rgb_color DriveLight = {0x00, 0xff, 0x00, 0};
  105.  
  106.  
  107. // Variables
  108. static UAE *the_app;
  109. static BitmapView *bitmap_view;
  110. static UAEWindow *bitmap_window;
  111. static bool reset_thyself = false;
  112.  
  113. static key_info old_key_info;
  114. static bool window_open;
  115. static bool LEDs[4];
  116.  
  117. static int the_argc;
  118. static char **the_argv;
  119.  
  120. static BJoystick *joy;
  121.  
  122.  
  123. // Array for converting Be keycodes to Amiga keycodes
  124. int keycode2amiga[128] = {
  125.     -1, AK_ESC, AK_F1, AK_F2, AK_F3, AK_F4, AK_F5, AK_F6,
  126.     AK_F7, AK_F8, AK_F9, AK_F10, -1, AK_mousestuff, -1, -1,
  127.  
  128.     -1, AK_BACKQUOTE, AK_1, AK_2, AK_3, AK_4, AK_5, AK_6,
  129.     AK_7, AK_8, AK_9, AK_0, AK_MINUS, AK_EQUAL, AK_BS, AK_HELP,
  130.  
  131.     AK_NPLPAREN, AK_NPRPAREN, -1, AK_NPDIV, AK_NPMUL, AK_NPSUB, AK_TAB, AK_Q,
  132.     AK_W, AK_E, AK_R, AK_T, AK_Y, AK_U, AK_I, AK_O,
  133.  
  134.     AK_P, AK_LBRACKET, AK_RBRACKET, AK_BACKSLASH, AK_DEL, AK_LALT, AK_RALT, AK_NP7,
  135.     AK_NP8, AK_NP9, AK_NPADD, AK_CAPSLOCK, AK_A, AK_S, AK_D, AK_F,
  136.  
  137.     AK_G, AK_H, AK_J, AK_K, AK_L, AK_SEMICOLON, AK_QUOTE, AK_RET,
  138.     AK_NP4, AK_NP5, AK_NP6, AK_LSH, AK_Z, AK_X, AK_C, AK_V,
  139.  
  140.     AK_B, AK_N, AK_M, AK_COMMA, AK_PERIOD, AK_SLASH, AK_RSH, AK_UP,
  141.     AK_NP1, AK_NP2, AK_NP3, AK_ENT, AK_CTRL, AK_LAMI, AK_SPC, AK_RAMI,
  142.  
  143.     AK_RALT, AK_LF, AK_DN, AK_RT, AK_NP0, AK_NPDEL, AK_LALT, AK_RALT,
  144.     AK_LTGT, -1, -1, -1, -1, -1, -1, -1,
  145.  
  146.     -1, -1, -1, -1, -1, -1, -1, -1,
  147.     -1, -1, -1, -1, -1, -1, -1, -1
  148. };
  149.  
  150.  
  151. /*
  152.  *  Create application object and start it
  153.  */
  154.  
  155. main(int argc, char **argv)
  156. {
  157.     // Copy command line arguments
  158.     the_argc = argc;
  159.     the_argv = new char *[argc];
  160.     for (int i=0; i<argc; i++)
  161.         the_argv[i] = strdup(argv[i]);
  162.  
  163.     the_app = new UAE();
  164.     the_app->Run();
  165.     delete the_app;
  166.     return 0;
  167. }
  168.  
  169.  
  170. /*
  171.  *  UAE Constructor: Initialize member variables
  172.  */
  173.  
  174. UAE::UAE() : BApplication('UAEm')
  175. {
  176.     the_bitmap = NULL;
  177.     main_window = NULL;
  178.     window_open = false;
  179. }
  180.  
  181.  
  182. /*
  183.  *  Arguments processed, create and start emulation
  184.  */
  185.  
  186. void UAE::ReadyToRun(void)
  187. {
  188.     // Start the emulation thread
  189.     the_thread = spawn_thread(thread_func, "UAE 68000", B_NORMAL_PRIORITY, this);
  190.     resume_thread(the_thread);
  191. }
  192.  
  193.  
  194. /*
  195.  *  Quit requested (either by menu or by closing the window)
  196.  */
  197.  
  198. bool UAE::QuitRequested(void)
  199. {
  200.     // Quit the thread
  201.     long l;
  202. //!!    uae_quit();
  203.     quit_program = 1;
  204.     regs.spcflags |= SPCFLAG_BRK;
  205.     wait_for_thread(the_thread, &l);
  206.  
  207.     return true;
  208. }
  209.  
  210.  
  211. /*
  212.  *  The thread's main function
  213.  */
  214.  
  215. long UAE::thread_func(void *obj)
  216. {
  217.     real_main(the_argc, the_argv);
  218.     return 0;
  219. }
  220.  
  221.  
  222. /*
  223.  *  Display "about" window
  224.  */
  225.  
  226. void UAE::AboutRequested(void)
  227. {
  228.     char str[256];
  229.  
  230.     sprintf(str, "     Un*x Amiga Emulator V%d.%d.%d\n"
  231.                  "          by Bernd Schmidt\n"
  232.                  "    BeBox port by Christian Bauer\n"
  233.                  "Additional porting by Patrick Hanevold", UAEMAJOR, UAEMINOR, UAEURSAMINOR);
  234.     BAlert *the_alert = new BAlert("", str, "OK");
  235.     the_alert->Go();
  236. }
  237.  
  238.  
  239. /*
  240.  *  Run file panel for floppy disk image selection
  241.  */
  242.  
  243. void UAEWindow::request_floppy(char *title, int drive_num)
  244. {
  245.     BMessage *sendmsg = new BMessage(B_REFS_RECEIVED);
  246.     sendmsg->AddInt32("uae_drive_num", drive_num);
  247. //!!    be_app->RunFilePanel(title, "Insert", NULL, false, sendmsg);
  248. }
  249.  
  250.  
  251. /*
  252.  *  File panel reply
  253.  */
  254.  
  255. void UAE::RefsReceived(BMessage *msg)
  256. {
  257.     ulong type;
  258.     long count;
  259.     char path[512];
  260.  
  261.     // Find drive number (default is 0)
  262.     int drive_num = msg->FindInt32("uae_drive_num");
  263. /*!!
  264.     // Find path of file
  265.     msg->GetInfo("refs", &type, &count);
  266.     for (int i=--count; i>=0; i--) {
  267.         record_ref item = msg->FindRef("refs", i);
  268.         if (item.database >= 0 && item.record >= 0 && does_ref_conform(item, "File")) {
  269.             BFile *file = new BFile;
  270.             file->SetRef(item);
  271.             file->GetPath(path, 511);
  272.  
  273.             // Eject old disk, then insert new one
  274.             disk_eject(drive_num);
  275.             disk_insert(drive_num, path);
  276.             delete file;
  277.         }
  278.     }
  279. */
  280. }
  281.  
  282.  
  283. /*
  284.  *  UAE Window constructor
  285.  */
  286.  
  287. LEDView *PowerLED, *DriveLED[4];
  288.  
  289. UAEWindow::UAEWindow(BRect frame, BBitmap *bitmap) : BWindow(frame,"UAE", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
  290. {
  291.     int i;
  292.  
  293.     // Initialize xcolors
  294.     {
  295.         BScreen scr(this);
  296.         i = 0;
  297.         for (int r=0; r<16; r++) {
  298.             for (int g=0; g<16; g++) {
  299.                 for (int b=0; b<16; b++)
  300.                     xcolors[i++] = scr.IndexForColor(r<<4 | r, g<<4 | g, b<<4 | b);
  301.             }
  302.         }
  303.     }
  304.  
  305.     // Move window to right position
  306.     Lock();
  307.     MoveTo(80, 80);
  308.  
  309.     // Set up menus
  310.     BMenuBar *MenuBar = new BMenuBar(Bounds(), "", B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, B_ITEMS_IN_ROW, true);
  311.  
  312.     BMenu *Menu;
  313.     BMenu *SubMenu;
  314.     BMenuItem *RateItem[7];
  315.  
  316.     Menu = new BMenu("Amiga"); MenuBar->AddItem(Menu);
  317.         SubMenu = new BMenu("Framerate"); Menu->AddItem(SubMenu);
  318.             SubMenu->SetRadioMode(true);
  319.             RateItem[0] = new BMenuItem("1/1", new BMessage(MSG_FR1)); SubMenu->AddItem(RateItem[0]);
  320.             RateItem[1] = new BMenuItem("1/2", new BMessage(MSG_FR2)); SubMenu->AddItem(RateItem[1]);
  321.             RateItem[2] = new BMenuItem("1/3", new BMessage(MSG_FR3)); SubMenu->AddItem(RateItem[2]);
  322.             RateItem[3] = new BMenuItem("1/4", new BMessage(MSG_FR4)); SubMenu->AddItem(RateItem[3]);
  323.             RateItem[4] = new BMenuItem("1/5", new BMessage(MSG_FR5)); SubMenu->AddItem(RateItem[4]);
  324.             RateItem[5] = new BMenuItem("1/6", new BMessage(MSG_FR6)); SubMenu->AddItem(RateItem[5]);
  325.             RateItem[6] = new BMenuItem("1/7", new BMessage(MSG_FR7)); SubMenu->AddItem(RateItem[6]);
  326.         Menu->AddItem(new BMenuItem("Reset", new BMessage(MSG_RESET)));
  327.         Menu->AddItem(new BMenuItem("Debugger", new BMessage(MSG_DEBUG)));
  328.     Menu = new BMenu("Floppy"); MenuBar->AddItem(Menu);
  329.         SubMenu = new BMenu("DF0:"); Menu->AddItem(SubMenu);
  330.             SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF0)));
  331.             SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF0)));
  332.         SubMenu = new BMenu("DF1:"); Menu->AddItem(SubMenu);
  333.             SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF1)));
  334.             SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF1)));
  335.         SubMenu = new BMenu("DF2:"); Menu->AddItem(SubMenu);
  336.             SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF2)));
  337.             SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF2)));
  338.         SubMenu = new BMenu("DF3:"); Menu->AddItem(SubMenu);
  339.             SubMenu->AddItem(new BMenuItem("Insert...", new BMessage(MSG_INSERT_DF3)));
  340.             SubMenu->AddItem(new BMenuItem("Eject", new BMessage(MSG_EJECT_DF3)));
  341.     RateItem[0]->SetMarked(true);
  342.     AddChild(MenuBar);
  343.  
  344.     // Resize window to fit menu bar
  345.     MenuBar->ResizeBy(-5*4, 0);    // Make room for LEDs
  346.     BRect MenuRect = MenuBar->Frame();
  347.     ResizeBy(0, MenuRect.bottom + 1);
  348.  
  349.     // Create LEDs
  350.     BRect PowerRect = Bounds();
  351.     PowerRect.bottom = MenuRect.bottom;
  352.     PowerRect.left = MenuRect.right+1;
  353.     PowerRect.right = PowerRect.left+3;
  354.     PowerLED = new LEDView(PowerRect, PowerLight, PowerDark);
  355.     AddChild(PowerLED);
  356.  
  357.     BRect DriveRect = PowerRect;
  358.     for (i=0; i<4; i++) {
  359.         DriveRect.left += 4;
  360.         DriveRect.right += 4;
  361.         DriveLED[i] = new LEDView(DriveRect, DriveLight, DriveDark);
  362.         AddChild(DriveLED[i]);
  363.     }
  364.  
  365.     // Create bitmap view
  366.     BRect BitmapRect = frame;
  367.     BitmapRect.OffsetTo(0, MenuRect.bottom + 1);
  368.     main_view = new BitmapView(BitmapRect, bitmap);
  369.     AddChild(main_view);
  370.     main_view->MakeFocus();
  371.     get_key_info(&old_key_info);
  372.  
  373.     bitmap_view = main_view;
  374.     bitmap_window = this;
  375.  
  376.     // Show window
  377.     Unlock();
  378.     Show();
  379.     window_open = true;
  380. }
  381.  
  382.  
  383. /*
  384.  *  Message received
  385.  */
  386.  
  387. void UAEWindow::MessageReceived(BMessage *msg)
  388. {
  389.     BMessage *msg2;
  390.  
  391.     switch(msg->what) {
  392.         case MSG_INSERT_DF0:
  393.             request_floppy("Insert floppy in DF0:", 0);
  394.             break;
  395.         case MSG_EJECT_DF0:
  396.             disk_eject(0);
  397.             break;
  398.         case MSG_INSERT_DF1:
  399.             request_floppy("Insert floppy in DF1:", 1);
  400.             break;
  401.         case MSG_EJECT_DF1:
  402.             disk_eject(1);
  403.             break;
  404.         case MSG_INSERT_DF2:
  405.             request_floppy("Insert floppy in DF2:", 2);
  406.             break;
  407.         case MSG_EJECT_DF2:
  408.             disk_eject(2);
  409.             break;
  410.         case MSG_INSERT_DF3:
  411.             request_floppy("Insert floppy in DF3:", 3);
  412.             break;
  413.         case MSG_EJECT_DF3:
  414.             disk_eject(3);
  415.             break;
  416.  
  417.         case MSG_FR1:
  418.             currprefs.framerate = 1;
  419.             break;
  420.         case MSG_FR2:
  421.             currprefs.framerate = 2;
  422.             break;
  423.         case MSG_FR3:
  424.             currprefs.framerate = 3;
  425.             break;
  426.         case MSG_FR4:
  427.             currprefs.framerate = 4;
  428.             break;
  429.         case MSG_FR5:
  430.             currprefs.framerate = 5;
  431.             break;
  432.         case MSG_FR6:
  433.             currprefs.framerate = 6;
  434.             break;
  435.         case MSG_FR7:
  436.             currprefs.framerate = 7;
  437.             break;
  438.  
  439.         case MSG_RESET:
  440.             reset_thyself = true;
  441.             break;
  442.  
  443.         case MSG_DEBUG:
  444.             activate_debugger();
  445.             break;
  446.  
  447.         case MSG_REDRAW:
  448.             MessageQueue()->Lock();
  449.             while ((msg2 = MessageQueue()->FindMessage(MSG_REDRAW, 0)) != NULL) {
  450.                 MessageQueue()->RemoveMessage(msg2);
  451.                 delete msg2;
  452.             }
  453.             MessageQueue()->Unlock();
  454.             Lock();
  455.             main_view->Draw(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1));
  456.             Unlock();
  457.             break;
  458.  
  459.         default:
  460.             BWindow::MessageReceived(msg);
  461.             break;
  462.     }
  463. }
  464.  
  465.  
  466. /*
  467.  *  Closing the window quits UAE
  468.  */
  469.  
  470. bool UAEWindow::QuitRequested(void)
  471. {
  472.     window_open = false;
  473.     be_app->PostMessage(B_QUIT_REQUESTED);
  474.     return false;
  475. }
  476.  
  477.  
  478. /*
  479.  *  Bitmap view constructor
  480.  */
  481.  
  482. BitmapView::BitmapView(BRect frame, BBitmap *bitmap) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
  483. {
  484.     the_bitmap = bitmap;
  485. }
  486.  
  487.  
  488. /*
  489.  *  Blit the bitmap
  490.  */
  491.  
  492. void BitmapView::Draw(BRect update)
  493. {
  494.     DrawBitmap(the_bitmap, update, update);
  495. }
  496.  
  497. void BitmapView::Draw(BRect from, BRect to)
  498. {
  499.     DrawBitmap(the_bitmap, from, to);
  500. }
  501.  
  502.  
  503. /*
  504.  *  Mouse moved
  505.  */
  506.  
  507. void BitmapView::MouseMoved(BPoint point, ulong transit, BMessage *message)
  508. {
  509.     newmousecounters = 0;
  510.     switch (transit) {
  511.         case B_ENTERED_VIEW:
  512.             newmousecounters = 1;
  513.             lastmx = point.x;
  514.             lastmy = point.y;
  515.             break;
  516.         case B_EXITED_VIEW:
  517.             break;
  518.         case B_INSIDE_VIEW:
  519.             lastmx = point.x;
  520.             lastmy = point.y;
  521.             break;
  522.     }
  523. }
  524.  
  525.  
  526. /*
  527.  *  LED
  528.  */
  529.  
  530. LEDView::LEDView(BRect frame, rgb_color active, rgb_color idle) : BView(frame, "", B_FOLLOW_NONE, B_WILL_DRAW)
  531. {
  532.     active_color = active;
  533.     idle_color = idle;
  534.     state = false;
  535.     SetViewColor(idle_color);
  536.     SetHighColor(idle_color);
  537.     bounds = Bounds();
  538. }
  539.  
  540. void LEDView::Draw(BRect update)
  541. {
  542.     FillRect(bounds);
  543. }
  544.  
  545. void LEDView::SetState(bool new_state)
  546. {
  547.     if (new_state != state) {
  548.         state = new_state;
  549.         Window()->Lock();
  550.         if (state) {
  551.             SetViewColor(active_color);
  552.             SetHighColor(active_color);
  553.         } else {
  554.             SetViewColor(idle_color);
  555.             SetHighColor(idle_color);
  556.         }
  557.         Draw(bounds);
  558.         Window()->Unlock();
  559.     }
  560. }
  561.  
  562.  
  563. /*
  564.  *  Redraw a line
  565.  */
  566.  
  567. void flush_line(int y)
  568. {
  569.     if (window_open) {
  570.         bitmap_window->Lock();
  571.         bitmap_view->Draw(BRect(0, y, currprefs.gfx_width-1, y));
  572.         bitmap_window->Unlock();
  573.     }
  574. }
  575.  
  576.  
  577. /*
  578.  *  Redraw a block
  579.  */
  580.  
  581. void flush_block(int ystart, int ystop)
  582. {
  583. }
  584.  
  585.  
  586. /*
  587.  *  Redraw the screen
  588.  */
  589.  
  590. void flush_screen(int ystart, int ystop)
  591. {
  592.     if (window_open)
  593.         bitmap_window->PostMessage(new BMessage(MSG_REDRAW));
  594. }
  595.  
  596.  
  597. /*
  598.  *  Init graphics
  599.  */
  600.  
  601. int graphics_setup(void)
  602. {
  603.     return 1;
  604. }
  605.  
  606. int graphics_init(void)
  607. {
  608.     return the_app->GraphicsInit();
  609. }
  610.  
  611. int UAE::GraphicsInit(void)
  612. {
  613.     if (currprefs.gfx_width < 320)
  614.         currprefs.gfx_width = 320;
  615.     if (currprefs.gfx_height < 200)
  616.         currprefs.gfx_height = 200;
  617.     if (currprefs.color_mode > 5)
  618.         fprintf(stderr, "Bad color mode selected. Using default.\n"), currprefs.color_mode = 0;
  619.  
  620.     gfxvidinfo.width = currprefs.gfx_width;
  621.     gfxvidinfo.height = currprefs.gfx_height;
  622.     gfxvidinfo.can_double = 0;
  623.  
  624.     // Allocate bitmap
  625.     the_bitmap = new BBitmap(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1), B_COLOR_8_BIT);
  626.  
  627.     // Set up vidinfo
  628.     gfxvidinfo.pixbytes = 1;
  629.     gfxvidinfo.rowbytes = the_bitmap->BytesPerRow();
  630.     gfxvidinfo.bufmem = (char *)the_bitmap->Bits();
  631.     gfxvidinfo.maxblocklines = 100; /* whatever... */
  632.  
  633.     // Open window
  634.     main_window = new UAEWindow(BRect(0, 0, currprefs.gfx_width-1, currprefs.gfx_height-1), the_bitmap);
  635.  
  636.     // Initialize mouse and keyboard variables
  637.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  638.     lastmx = lastmy = 0;
  639.     newmousecounters = 0;
  640.  
  641.     return true;
  642. }
  643.  
  644.  
  645. /*
  646.  * Exit graphics
  647.  */
  648.  
  649. void graphics_leave(void)
  650. {
  651.     the_app->GraphicsLeave();
  652. }
  653.  
  654. void UAE::GraphicsLeave(void)
  655. {
  656.     // Deallocate bitmap
  657.     delete the_bitmap;
  658. }
  659.  
  660.  
  661. /*
  662.  *  Poll mouse and keyboard
  663.  */
  664.  
  665. void handle_events(void)
  666. {
  667.     key_info the_key_info;
  668.     int be_code, be_byte, be_bit, amiga_code;
  669.     BPoint mouse_point;
  670.     ulong mouse_buttons;
  671.  
  672.     if (reset_thyself) {
  673. //!!    uae_reset();
  674.         m68k_reset();
  675.         reset_thyself = false;
  676.     }
  677.  
  678.     // Redraw drive LEDs
  679.     for (int i=0; i<4; i++)
  680.         DriveLED[i]->SetState(LEDs[i]);
  681.  
  682.     if (window_open && bitmap_window->IsActive()) {
  683.  
  684.         get_key_info(&the_key_info);
  685.         bitmap_window->Lock();
  686.         bitmap_view->GetMouse(&mouse_point, &mouse_buttons, false);
  687.         bitmap_window->Unlock();
  688.  
  689.         // Keyboard
  690.         if (memcmp(the_key_info.key_states, old_key_info.key_states, sizeof(the_key_info.key_states))) {
  691.             for (be_code=0; be_code<0x80; be_code++) {
  692.                 be_byte = be_code >> 3;
  693.                 be_bit = 1 << (~be_code & 7);
  694.  
  695.                 // Key state changed?
  696.                 if ((the_key_info.key_states[be_byte] & be_bit)
  697.                      != (old_key_info.key_states[be_byte] & be_bit)) {
  698.  
  699.                     amiga_code = keycode2amiga[be_code];
  700.                     if (the_key_info.key_states[be_byte] & be_bit) {
  701.  
  702.                         // Key pressed
  703.                         if (amiga_code == AK_mousestuff)
  704.                             togglemouse();
  705.                         else
  706.                             record_key(amiga_code << 1);
  707.                     } else {
  708.  
  709.                         // Key released
  710.                         record_key((amiga_code << 1) | 1);
  711.                     }
  712.                 }
  713.             }        
  714.             old_key_info = the_key_info;
  715.         }
  716.  
  717.         // "Affengriff"
  718.         if ((the_key_info.key_states[0x5c >> 3] & (1 << (~0x5c & 7)))
  719.          && (the_key_info.key_states[0x5d >> 3] & (1 << (~0x5d & 7)))
  720.          && (the_key_info.key_states[0x5f >> 3] & (1 << (~0x5f & 7))))
  721.             m68k_reset();
  722.  
  723.         // Scroll lock toggles inhibit_frame
  724.         if (inhibit_frame != 2)
  725.             inhibit_frame = the_key_info.key_states[0x0f >> 3] & (1 << (~0x0f & 7));
  726.  
  727.         // Mouse buttons
  728.         if (mouse_point.x >= 0 && mouse_point.y >= 0 && mouse_point.x < currprefs.gfx_width && mouse_point.y < currprefs.gfx_height) {
  729.             buttonstate[0] = mouse_buttons & B_PRIMARY_MOUSE_BUTTON;
  730.             buttonstate[1] = mouse_buttons & B_TERTIARY_MOUSE_BUTTON;
  731.             buttonstate[2] = mouse_buttons & B_SECONDARY_MOUSE_BUTTON;
  732.         }
  733.     }
  734. }
  735.  
  736.  
  737. /*
  738.  *  Joystick routines
  739.  */
  740.  
  741. extern "C" {
  742. void init_joystick(void);
  743. void close_joystick(void);
  744. void read_joystick(int nr, unsigned int *dir, int *button);
  745. };
  746.  
  747. int nr_joysticks;
  748.  
  749. void read_joystick(int nr, unsigned int *dir, int *button)
  750. {
  751.     static int joy_minx = 32767, joy_maxx = 0,
  752.                joy_miny = 32767, joy_maxy = 0;
  753.     int left = 0, right = 0, top = 0, bot = 0;
  754.  
  755.     *dir = 0;
  756.     *button = 0;
  757.  
  758.     if (nr >= nr_joysticks)
  759.         return;
  760.  
  761.     if (joy->Update() != B_ERROR) {
  762.         if (joy->horizontal > joy_maxx)
  763.             joy_maxx = joy->horizontal;
  764.         if (joy->horizontal < joy_minx)
  765.             joy_minx = joy->horizontal;
  766.         if (joy->vertical > joy_maxy)
  767.             joy_maxy = joy->vertical;
  768.         if (joy->vertical < joy_miny)
  769.             joy_miny = joy->vertical;
  770.  
  771.         if (joy_maxx-joy_minx < 100 || joy_maxy-joy_miny < 100)
  772.             return;
  773.  
  774.         if (joy->horizontal < (joy_minx + (joy_maxx-joy_minx)/3))
  775.             right = 1;
  776.         else if (joy->horizontal > (joy_minx + 2*(joy_maxx-joy_minx)/3))
  777.             left = 1;
  778.  
  779.         if (joy->vertical < (joy_miny + (joy_maxy-joy_miny)/3))
  780.             bot = 1;
  781.         else if (joy->vertical > (joy_miny + 2*(joy_maxy-joy_miny)/3))
  782.             top = 1;
  783.  
  784.         if (left) top = !top;
  785.         if (right) bot = !bot;
  786.         *dir = bot | (right << 1) | (top << 8) | (left << 9);
  787.         *button = !joy->button1;
  788.     }
  789. }
  790.  
  791. void init_joystick(void)
  792. {
  793.     joy = new BJoystick();
  794.     joy->Open("joystick1");
  795.     nr_joysticks = 1;
  796. }
  797.  
  798. void close_joystick(void)
  799. {
  800.     joy->Close();
  801.     delete joy;
  802. }
  803.  
  804.  
  805. /*
  806.  *  Sound routines
  807.  */
  808.  
  809. extern "C" {
  810. extern int sound_available;
  811. extern int smplcnt;
  812. extern int init_sound(void);
  813. extern int setup_sound(void);
  814. extern void flush_sound_buffer(void);
  815. extern void init_sound_table8(void);
  816. extern void init_sound_table16(void);
  817. extern void sample8_handler(void);
  818. extern void sample16_handler(void);
  819. };
  820.  
  821. uae_u16 *sndbuffer;
  822. uae_u16 *sndbufpt;
  823. int sndbufsize;
  824.  
  825. static uae_u8 *buffers[2] = {NULL, NULL};
  826. static int buf_num;
  827. static BDACStream *the_stream;
  828. static BSubscriber *the_sub;
  829. static bool sound_ready = false;
  830. static sem_id sound_sync_sem;
  831.  
  832. bool stream_func(void *arg, char *buf, size_t count, void *header);
  833.  
  834. int init_sound(void)
  835. {
  836.     sound_sync_sem = create_sem(0, "UAE Sound Sync Semaphore");
  837.     the_stream = new BDACStream();
  838.     the_sub = new BSubscriber("UAE DAC subscriber");
  839.  
  840.     if (!currprefs.produce_sound)
  841.         return 0;
  842.     sound_ready = the_sub->Subscribe(the_stream) == B_NO_ERROR;
  843.     if (!sound_ready)
  844.         return 0;
  845.  
  846.     sndbufsize = 44100 / 8 * 4;
  847.     buffers[0] = new uae_u8[sndbufsize];
  848.     buffers[1] = new uae_u8[sndbufsize];
  849.     memset(buffers[0], 0, sndbufsize);
  850.     memset(buffers[1], 0, sndbufsize);
  851.     buf_num = 0;
  852.     sndbufpt = sndbuffer = (uae_u16 *)buffers[buf_num];
  853.  
  854.     init_sound_table16();
  855.     eventtab[ev_sample].handler = sample16_handler;
  856.     sample_evtime = (long)maxhpos * maxvpos * 50 / 44100;
  857.  
  858.     sound_available = 1;
  859.     the_stream->SetSamplingRate(44100);
  860.     the_stream->SetStreamBuffers(sndbufsize, 4);
  861.     the_sub->EnterStream(NULL, true, NULL, stream_func, NULL, true);
  862.     return 1;
  863. }
  864.  
  865. int setup_sound(void)
  866. {
  867.     sound_available = 1;
  868.     return 1;
  869. }
  870.  
  871. void close_sound(void)
  872. {
  873.     if (sound_ready) {
  874.         the_sub->ExitStream(true);
  875.         the_stream->SetStreamBuffers(4096, 8);
  876.         the_sub->Unsubscribe();
  877.         sound_ready = false;
  878.     }
  879.     delete the_sub;
  880.     delete the_stream;
  881.  
  882.     delete_sem(sound_sync_sem);
  883.  
  884.     delete buffers[0];
  885.     delete buffers[1];
  886. }
  887.  
  888. void flush_sound_buffer(void)
  889. {
  890.     if (sound_ready) {
  891.         long l;
  892.         get_sem_count(sound_sync_sem, &l);
  893.         if (l > 0)
  894.             acquire_sem_etc(sound_sync_sem, l+1, 0, 0);
  895.         else
  896.             acquire_sem(sound_sync_sem);
  897.     }
  898.  
  899.     sndbufpt = sndbuffer = (uae_u16 *)buffers[buf_num];
  900.     buf_num ^= 1;
  901. }
  902.  
  903. bool stream_func(void *arg, char *buf, size_t count, void *header)
  904. {
  905.     memcpy(buf, buffers[buf_num], count);
  906.     release_sem(sound_sync_sem);
  907.     return true;
  908. }
  909.  
  910.  
  911. /*
  912.  *  Misc routines
  913.  */
  914.  
  915. int debuggable(void)
  916. {
  917.     return true;
  918. }
  919.  
  920. int needmousehack(void)
  921. {
  922.     return true;
  923. }
  924.  
  925. void LED(int on)
  926. {
  927.     PowerLED->SetState(!on);
  928. }
  929.  
  930. void setup_brkhandler(void)
  931. {
  932. }
  933.  
  934. void gui_changesettings(void)
  935. {
  936.     
  937. }
  938.  
  939. void gui_led(int led, int on)
  940. {
  941.     if (led > 0 && led < 5)
  942.         LEDs[led-1] = on;
  943. }
  944.  
  945. int gui_init(void)
  946. {
  947.     LEDs[0] = LEDs[1] = LEDs[2] = LEDs[3] = false;
  948.     quit_program = 0;
  949.     return 0;
  950. }
  951.  
  952. void gui_exit(void)
  953. {
  954. }
  955.  
  956. int gui_update(void)
  957. {
  958.     return 0;
  959. }
  960.  
  961. void gui_filename(int num, const char *name)
  962. {
  963. }
  964.  
  965. static void getline(char *p)
  966. {
  967. }
  968.  
  969. void gui_handle_events(void)
  970. {
  971. }
  972.  
  973. void write_log (const char *buf)
  974. {
  975.     fprintf (stderr, buf);
  976. }
  977.